#include "shmem.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <assert.h>
#include "cJSON.h"
#include <semaphore.h>

// 数据类型定义（与读取程序保持一致）
typedef enum
{
    TYPE_BOOL = 1,  // 布尔类型
    TYPE_INT = 2,   // 整数类型
    TYPE_FLOAT = 3, // 浮点类型
} DataType;

// STM32设备点表项
typedef struct
{
    uint16_t key;   // 点表键值
    char name[32];  // 点表名称
    DataType type;  // 数据类型
    uint8_t status; // 状态标志(0=无效,1=有效)
    union
    {
        int int_value;
        float float_value;
        int bool_value;
    } value;
} STM32Item;

// Modbus设备点表项
typedef struct
{
    uint16_t key;   // 点表键值
    char name[32];  // 点表名称
    uint16_t addr;  // Modbus地址
    DataType type;  // 数据类型
    uint8_t status; // 状态标志(0=无效,1=有效)
    union
    {
        int int_value;
        float float_value;
        int bool_value;
    } value;
} ModbusItem;

// 完整配置结构体
typedef struct
{
    int stm32_count;            // STM32点表项数量
    STM32Item stm32_items[100]; // 与写入程序保持一致

    int modbus_count;             // Modbus点表项数量
    ModbusItem modbus_items[100]; // 与写入程序保持一致

    // 其他配置信息
    char version[10]; // 配置版本
    struct
    {
        int type;   // 报告类型
        int period; // 报告周期
    } report;
    struct
    {
        char addr[20]; // MQTT服务器地址
        int port;      // MQTT服务器端口
    } mqtt_server;
    struct
    {
        char addr[20]; // Modbus设备地址
        int port;      // Modbus设备端口
    } mb_dev;
    struct
    {
        char addr[20]; // Modbus应用地址
        int port;      // Modbus应用端口
    } mb_app;
} ConfigData;

#define SHARED_MEM_NAME "point_table_shm"
#define JSON_FILENAME "pointTable.json"
#define SEM_NAME "/point_table_shm_sem"

// 读取JSON文件内容
char *read_json_file(const char *filename)
{
    int fd = open(filename, O_RDONLY);
    if (fd < 0)
    {
        perror("Failed to open JSON file");
        return NULL;
    }

    struct stat st;
    if (fstat(fd, &st) < 0)
    {
        perror("Failed to get file status");
        close(fd);
        return NULL;
    }

    char *buffer = (char *)malloc(st.st_size + 1);
    if (buffer == NULL)
    {
        perror("Failed to allocate memory");
        close(fd);
        return NULL;
    }

    ssize_t bytes_read = read(fd, buffer, st.st_size);
    if (bytes_read < 0)
    {
        perror("Failed to read JSON file");
        free(buffer);
        close(fd);
        return NULL;
    }

    buffer[bytes_read] = '\0';
    close(fd);
    return buffer;
}

// 解析JSON中的字符串字段
void parse_string(cJSON *root, const char *path, char *dest, size_t dest_size)
{
    cJSON *obj = cJSON_GetObjectItem(root, path);
    if (obj != NULL && obj->type == cJSON_String)
    {
        strncpy(dest, obj->valuestring, dest_size - 1);
        dest[dest_size - 1] = '\0';
    }
}

// 解析JSON中的整数字段
void parse_int(cJSON *root, const char *path, int *dest)
{
    cJSON *obj = cJSON_GetObjectItem(root, path);
    if (obj != NULL && obj->type == cJSON_Number)
    {
        *dest = obj->valueint;
    }
}

// 解析STM32点表项
int parse_stm32_items(cJSON *root, STM32Item *items, int max_count)
{
    cJSON *stm32_obj = cJSON_GetObjectItem(root, "stm32");
    if (stm32_obj == NULL || stm32_obj->type != cJSON_Object)
    {
        printf("Warning: No valid 'stm32' object found in JSON\n");
        return 0;
    }

    cJSON *data_array = cJSON_GetObjectItem(stm32_obj, "data");
    if (data_array == NULL || data_array->type != cJSON_Array)
    {
        printf("Warning: No valid 'stm32.data' array found in JSON\n");
        return 0;
    }

    int array_size = cJSON_GetArraySize(data_array);
    int count = (array_size > max_count) ? max_count : array_size;

    for (int i = 0; i < count; i++)
    {
        cJSON *item = cJSON_GetArrayItem(data_array, i);
        if (item == NULL || item->type != cJSON_Object)
        {
            printf("Warning: Invalid item at index %d in 'stm32.data'\n", i);
            continue;
        }

        STM32Item *current_item = &items[i];
        memset(current_item, 0, sizeof(STM32Item)); // 初始化结构体

        cJSON *key_obj = cJSON_GetObjectItem(item, "key");
        cJSON *name_obj = cJSON_GetObjectItem(item, "name");
        cJSON *type_obj = cJSON_GetObjectItem(item, "type");

        if (key_obj != NULL && key_obj->type == cJSON_Number)
            current_item->key = key_obj->valueint;

        if (name_obj != NULL && name_obj->type == cJSON_String)
            strncpy(current_item->name, name_obj->valuestring, sizeof(current_item->name) - 1);

        if (type_obj != NULL && type_obj->type == cJSON_Number)
        {
            current_item->type = type_obj->valueint;
            // 验证类型值有效性
            if (current_item->type < TYPE_BOOL || current_item->type > TYPE_FLOAT)
            {
                printf("Warning: Invalid type %d for item %d in 'stm32.data'\n",
                       current_item->type, i);
                current_item->type = TYPE_INT; // 默认类型
            }
        }
        else
        {
            current_item->type = TYPE_INT; // 默认类型
        }

        current_item->status = 1; // 设置为有效

        // 根据type设置value
        switch (current_item->type)
        {
        case TYPE_BOOL:
            current_item->value.bool_value = 0;
            break;
        case TYPE_INT:
            current_item->value.int_value = 0;
            break;
        case TYPE_FLOAT:
            current_item->value.float_value = 0.0f;
            break;
        default:
            current_item->value.int_value = 0;
            break;
        }
    }
    return count;
}

// 解析Modbus点表项
int parse_modbus_items(cJSON *root, ModbusItem *items, int max_count)
{
    cJSON *modbus_obj = cJSON_GetObjectItem(root, "modbus");
    if (modbus_obj == NULL || modbus_obj->type != cJSON_Object)
    {
        printf("Warning: No valid 'modbus' object found in JSON\n");
        return 0;
    }

    cJSON *data_array = cJSON_GetObjectItem(modbus_obj, "data");
    if (data_array == NULL || data_array->type != cJSON_Array)
    {
        printf("Warning: No valid 'modbus.data' array found in JSON\n");
        return 0;
    }

    int array_size = cJSON_GetArraySize(data_array);
    int count = (array_size > max_count) ? max_count : array_size;

    for (int i = 0; i < count; i++)
    {
        cJSON *item = cJSON_GetArrayItem(data_array, i);
        if (item == NULL || item->type != cJSON_Object)
        {
            printf("Warning: Invalid item at index %d in 'modbus.data'\n", i);
            continue;
        }

        ModbusItem *current_item = &items[i];
        memset(current_item, 0, sizeof(ModbusItem)); // 初始化结构体

        cJSON *key_obj = cJSON_GetObjectItem(item, "key");
        cJSON *name_obj = cJSON_GetObjectItem(item, "name");
        cJSON *addr_obj = cJSON_GetObjectItem(item, "addr");
        cJSON *type_obj = cJSON_GetObjectItem(item, "type");

        if (key_obj != NULL && key_obj->type == cJSON_Number)
            current_item->key = key_obj->valueint;

        if (name_obj != NULL && name_obj->type == cJSON_String)
            strncpy(current_item->name, name_obj->valuestring, sizeof(current_item->name) - 1);

        if (addr_obj != NULL && addr_obj->type == cJSON_Number)
            current_item->addr = addr_obj->valueint;

        if (type_obj != NULL && type_obj->type == cJSON_Number)
        {
            current_item->type = type_obj->valueint;
            // 验证类型值有效性
            if (current_item->type < TYPE_BOOL || current_item->type > TYPE_FLOAT)
            {
                printf("Warning: Invalid type %d for item %d in 'modbus.data'\n",
                       current_item->type, i);
                current_item->type = TYPE_INT; // 默认类型
            }
        }
        else
        {
            current_item->type = TYPE_INT; // 默认类型
        }

        current_item->status = 1; // 设置为有效

        // 根据type设置value
        switch (current_item->type)
        {
        case TYPE_BOOL:
            current_item->value.bool_value = 0;
            break;
        case TYPE_INT:
            current_item->value.int_value = 0;
            break;
        case TYPE_FLOAT:
            current_item->value.float_value = 0.0f;
            break;
        default:
            current_item->value.int_value = 0;
            break;
        }
    }
    return count;
}

int main()
{
    struct shm_param shm;
    char *json_data = read_json_file(JSON_FILENAME);
    if (json_data == NULL)
    {
        return 1;
    }

    // --------------------- 信号量处理 ---------------------
    sem_t *shm_sem = sem_open(SEM_NAME, O_CREAT, 0666, 1); // 创建信号量并初始化为1
    if (shm_sem == SEM_FAILED)
    {
        perror("Failed to create semaphore");
        free(json_data);
        return 1;
    }

    // 加锁（获取信号量）
    if (sem_wait(shm_sem) != 0)
    {
        perror("sem_wait failed");
        sem_close(shm_sem);
        free(json_data);
        return 1;
    }

    // --------------------- 共享内存处理 ---------------------
    const size_t SHARED_MEM_SIZE = sizeof(ConfigData);
    if (shm_init(&shm, SHARED_MEM_NAME, SHARED_MEM_SIZE, 1) != 0)
    {
        fprintf(stderr, "Failed to initialize shared memory\n");
        sem_post(shm_sem); // 解锁后报错
        sem_close(shm_sem);
        free(json_data);
        return 1;
    }

    void *shm_addr = shm_getaddr(&shm);
    if (shm_addr == NULL)
    {
        fprintf(stderr, "Failed to attach shared memory\n");
        sem_post(shm_sem);
        sem_close(shm_sem);
        free(json_data);
        return 1;
    }

    // --------------------- 解析JSON数据 ---------------------
    ConfigData config;
    memset(&config, 0, sizeof(ConfigData));
    cJSON *root = cJSON_Parse(json_data);
    if (!root)
    {
        const char *error_ptr = cJSON_GetErrorPtr();
        if (error_ptr != NULL)
        {
            fprintf(stderr, "Error before: %s\n", error_ptr);
        }
        free(json_data);
        sem_post(shm_sem);
        sem_close(shm_sem);
        return 1;
    }

    // 解析各字段
    parse_string(root, "version", config.version, sizeof(config.version));
    parse_int(root, "report/type", &config.report.type);
    parse_int(root, "report/period", &config.report.period);
    parse_string(root, "mqtt_server/addr", config.mqtt_server.addr, sizeof(config.mqtt_server.addr));
    parse_int(root, "mqtt_server/port", &config.mqtt_server.port);
    parse_string(root, "mb_dev/addr", config.mb_dev.addr, sizeof(config.mb_dev.addr));
    parse_int(root, "mb_dev/port", &config.mb_dev.port);
    parse_string(root, "mb_app/addr", config.mb_app.addr, sizeof(config.mb_app.addr));
    parse_int(root, "mb_app/port", &config.mb_app.port);

    // 解析STM32点表
    config.stm32_count = parse_stm32_items(root, config.stm32_items, 100);

    // 解析Modbus点表
    config.modbus_count = parse_modbus_items(root, config.modbus_items, 100);

    // 修改配置数据（示例）
    config.report.type = 1;
    config.report.period = 10;
    
    // --------------------- 写入共享内存 ---------------------
    if (shm_write(&shm, &config, sizeof(ConfigData)) != 0)
    {
        fprintf(stderr, "Failed to write to shared memory\n");
        cJSON_Delete(root);
        free(json_data);
        sem_post(shm_sem); // 解锁后报错
        sem_close(shm_sem);
        return 1;
    }


    printf("Successfully wrote data to shared memory\n");
    printf("STM32 Items: %d\n", config.stm32_count);
    printf("Modbus Items: %d\n", config.modbus_count);

    // --------------------- 资源清理 ---------------------
    cJSON_Delete(root);
    free(json_data);

    // 解锁信号量（关键步骤，允许其他进程访问共享内存）
    if (sem_post(shm_sem) != 0)
    {
        perror("sem_post failed");
    }
    sem_close(shm_sem); // 关闭信号量描述符（不删除信号量）

    return 0;
}